﻿#ifndef _STREAM_FRAME_SHMEM_H_
#define _STREAM_FRAME_SHMEM_H_

#include <map>
#include <string>
#include <stdint.h>
#include <mutex>
#include "frame_utility.h"
#ifdef _WIN32
#include <windows.h>
#endif
using namespace std;
#define ShareMemFlag  *(uint32_t*)"SHMF"  //帧头
//以下的类,供多进程使用合适 
class CFrame_sharemem
{
    public:
        CFrame_sharemem();
        virtual ~CFrame_sharemem();

    public:
        int Open(const char* shmName, int ch, int bufSize, bool is_producer,char * clientName = NULL);
        int Close();
        int WriteFrame(uint8_t* buf, uint32_t size, int frameType, int64_t pts = 0, int codeType = 0);
       // int ReadFrame(uint8_t* pFrameData, uint32_t frameLen, int* isKeyFrame = NULL);
        int putFrame(uint8_t*pFrameData, uint32_t frameLen, bool bCover = true);
        int ReadFrame(uint8_t* buf, uint32_t frameLen, int *isKeyFrame = NULL);

        unsigned char* GetBufOffset(uint32_t size, uint32_t *leaf_size, unsigned char**tail_buf);
        unsigned char* GetFreeBuf(unsigned char**tail_buf, uint32_t *leaf_size);
		
        int SeekTime(int64_t cur_ms,int pre_sec);

    public:

        int read(unsigned char *buf, uint32_t size,  bool bPeek);
        int write(unsigned char *buf, uint32_t data_size);
        void reset();

        int ConsumeBuf(uint32_t size);

        int ProductBuf(uint32_t size);

        //生产一个空帧去补齐．
        int ProducEmptyFrm(uint32_t size);

		//镜像帧头,便于读取帧
		int MirrorFrameHead();

#ifndef _WIN32
        int DestryMemory();
#endif
        uint32_t GetDataSize();

        uint32_t GetFreeSize()
        {
            return  m_shmSize - GetDataSize();
        }
    protected:
        int read_buf(uint32_t offset, unsigned char *buf, uint32_t size, bool bConsume);
		int reg_user(char* userName);
		int unreg_user(char* userName);
    public:

        uint32_t GetFIFOSize()
        {
            return  m_shmSize;
        }

        bool IsEmpty()
        {
            return ( m_pInfoBase->m_pidx ==  m_pInfo->m_cidx);
        }

        uint32_t GetCurWarter()
        {
            return  (GetDataSize() * 100) / m_shmSize;
        }

        bool IsOpen()
        {
            return m_bOpened;
        }


    protected:
#ifndef _WIN32
        struct flock *file_lock(short type, short whence);
#endif
        void lock();
        void unlock();
        void *CreateShm(const char *name, int size);
        static const uint32_t FRAME_HEADLEN;
    private:
        //pthread_mutex_t* mMutex;

        unsigned char *m_pShareMem;
        char m_shmName[64];
		string m_clientName;
        bool m_bOpened;
        bool m_accessMode;
        int m_shmSize;
        int m_lockFd;
        int m_fd;
		int m_clientIdx;
        int m_last_frm_sz;
        uint32_t  m_frameNo = 0;
        mutex m_lock;
#ifdef _WIN32
        HANDLE m_hMapFile;
#else

#endif
    protected:


        typedef struct _SHARE_BUF_INFO_
        {
			char     clientName[32];
            uint32_t m_pidx;		//product index
            uint32_t m_cidx;	    //consume index
            uint32_t m_buf_size;	//
        } SHARE_BUF_INFO;

        typedef struct _BASE_FRM_INFO_
        {
            uint32_t  shmTag;
            uint32_t  key_idx;
            uint32_t  max_key_frm;
            int64_t   last_tm;
        }BASE_FRM_INFO;
        
        typedef struct _CACHE_FRM_INFO_
        {
            int64_t   time;
            uint32_t  pos;
            uint32_t  frmNo;
            uint32_t  len;
            uint8_t   frameType;	//数据流类型
        }CACHE_FRM_INFO;
		
        SHARE_BUF_INFO *m_pInfoBase;
        SHARE_BUF_INFO *m_pInfo;
        BASE_FRM_INFO* m_base_frm;

        unsigned char*m_buf;
		CFrmUtility     m_frmTool;
      

        typedef enum
        {
            FIFO_ERR_SIZE = -3005,
            FIFO_ERR_NOTENOUGH = -3004,
            FIFO_ERR_NODATA = -3002,
            FIFO_ERR_OPENED = -3001,
            FIFO_ERR_NOOPEN = -3000,
            FIFO_ERR_PARAM = -2009,
            FIFO_ERR_TIMEOUT = -2008,
            FIFO_ERR_OVERDATA = -2007,
            FIFO_NO_EER = 0,
        }ERR_FIFO_E;
        RD_FRAME_H  m_frmHead;
};

#endif  //_STREAM_FRAME_SHMEM_H_